Los mapas estáticos son útiles para crear figuras para informes y presentaciones. A veces, sin embargo, deseamos interactuar con sus datos. Podemos utilizar el paquete leaflet de R para superponer sus datos sobre mapas interactivos. Puedes pensar en ello como mapas de Google con sus datos superpuestos en la parte superior.
Leaflet es una librería de JavaScript de código abierto que se puede utilizar para crear mapas interactivos compatibles con dispositivos móviles. Una vez instalada, se puede usar este paquete en la consola R, dentro de los documentos RMarkdown y dentro de las aplicaciones Shiny.
Se puede crear un mapa con leaflet con estos pasos básicos:
Crear un mapa llamando a leaflet().
Agregar capas (características) al mapa utilizando funciones de
capa (por ejemplo, addTiles, addMarkers,
addPolygons).
Repetir el paso 2 como se desee.
Imprimir el mapa para mostrarlo.
Aquí tenemos un ejemplo básico, donde se muestra dónde se encuentra la biblioteca de la Universidad de Alicante, lugar del aula del Máster en Ciencia de Datos.
library(leaflet)
m <- leaflet() %>%
addTiles() %>% # Add default OpenStreetMap map tiles
addMarkers(lng=-0.511828, lat=38.383279, popup="Aula del Máster de Ciencia de Datos")
m # Print the map
En la primera línea indicamos que utilice la librería
leaflet, después hemos creado un objeto m,
mediante el operador habitua leaflet. Con la función
addTiles() estamos incorporando un mapa de Tiles,
siendo OpenStreetMap el que utiliza por defecto. A continuación añadimos
un marcador al mapa conaddMarkers(), pasando como
parámetros las coordenadas geográficas de un punto (lng y lat) y creamos
un popup con el texto “Aula del Máster de Ciencia de Datos”. Por último,
solo nos queda mostrar el mapa por pantalla el objeto creado
m.
RStudio nos permite exportar el mapa que hemos creado. En el
menú de visualización del mapa, RStudio dispone de la opción
Export. La primera vez que la utilicemos nos indicará que
necesita descargar nuevos paquetes. Seleccionamos
Save as Web Page y nos crea un archivo html con
todo lo necesario para ver el mapa.
Podemos manipular los atributos del widget de mapa utilizando una
serie de métodos. Consulte la página de ayuda ?SetView para
obtener más detalles.
setView() establece el centro de la vista del mapa y
el nivel de zoom;
fitBounds() ajusta la vista en el rectángulo [lng1,
lat1] - [lng2, lat2];
clearBounds() borra el límite, por lo que la vista
se determinará automáticamente por el rango de datos de latitud/longitud
en las capas del mapa, si se proporcionan.
El objeto de datos
Tanto leaflet() como las funciones de la capa de mapa
tienen un parámetro de datos opcional que está diseñado para recibir
datos espaciales en una de varias formas:
Desde la base R:
matriz lng / lat.
marco de datos con columnas lng/lat.
Desde el paquete sp:
SpatialPoints [DataFrame].
Línea / Líneas.
SpatialLines [DataFrame].
Polígono / polígonos.
SpatialPolygons [DataFrame].
*Desde el paquete de mapas:
map()El argumento de datos se utiliza para derivar datos espaciales para
funciones que lo necesitan; por ejemplo, si los datos son un objeto
SpatialPolygonsDataFrame, entonces llamar a
addPolygons en ese widget de mapa sabrá agregar los
polígonos de ese SpatialPolygonsDataFrame.
Es sencillo derivar estas variables de objetos sp, ya que siempre representan datos espaciales de la misma manera. Por otro lado, para una matriz o marco de datos normal, cualquier columna numérica podría contener datos espaciales. Entonces recurrimos a adivinar en función de los nombres de las columnas:
la variable de latitud se adivina buscando columnas denominadas lat o latitud (no distingue entre mayúsculas y minúsculas).
la variable de longitud se adivina buscando lng, long o longitude.
Siempre puede identificar explícitamente las columnas de latitud/longitud proporcionando argumentos lng y lat a la función de capa.
Leaflet admite mapas base que utilizan mosaicos de mapas, popularizados por Google Maps y ahora utilizados por casi todos los mapas web interactivos.
La forma más sencilla de añadir capas es mediante
addTiles()sin argumentos; por defecto, se utilizan los de OSM. Alternativamente, se pueden agregar muchos mapas base gratuitos populares de terceros mediante la funciónaddProviderTiles(), que se implementa mediante el complemento de proveedores leaflet-providers plugin. ôdmeos consultar aquí el conjunto completo.
Los proveedores de leaflet (leaflet.providers) proporcionan capas de mapas de diferentes proveedores, incluidos OpenStreetMap, Stamen, Esri y OpenWeatherMap. Se puede obtener una vista previa de la lista completa de capas de uso gratuito. Esta página le mostrará el nombre para usar con leaflet-Suppliers.js y el código para usarlo sin dependencias.
Para su comodidad, Leaflet también proporciona una lista
con nombre de todos los proveedores de mapas de terceros que son
compatibles con el complemento. Esto le permite utilizar la función de
autocompletar de su R IDE favorito (como RStudio) y no tener que
recordar ni buscar proveedores de mosaicos compatibles; simplemente
escriba providers$ y elija una de las opciones. También
puede escribir names(providers) para ver todas las
opciones.
Existen proveedores de mapas que requieren un registro previo. Veamos alguno de ellos.
Mapbox
In order to use Mapbox maps, you must register. You can get map_ID (e.g. “mapbox/satellite-v9”) and ACCESS_TOKEN from Mapbox projects:
L.tileLayer.provider('MapBox', {
id: '<insert map_ID here>',
accessToken: '<insert ACCESS_TOKEN here>'
}).addTo(map);
The currently-valid Mapbox map styles, to use for map_IDs, are listed in the Mapbox documentation - only the final part of each is required, e.g. “mapbox/light-v10”.
Esri/ArcGIS
In order to use ArcGIS maps, you must register and abide by the terms of service. No special syntax is required.
Stadia Maps
In order to use Stadia maps, you must register. Once registered, you can whitelist your domain within your account settings.
HERE and HEREv3 (formerly Nokia).
In order to use HEREv3 layers, you must register. Once registered, you can create an apiKey which you have to pass to L.tileLayer.provider in the options:
L.tileLayer.provider('HEREv3.terrainDay', {
apiKey: '<insert apiKey here>'
}).addTo(map);
You can still pass app_id and app_code in legacy projects:
L.tileLayer.provider('HERE.terrainDay', {
app_id: '<insert ID here>',
app_code: '<insert ID here>'
}).addTo(map);
Jawg Maps
In order to use Jawg Maps, you must register. Once registered, your access token will be located here and you will access to all Jawg default maps (variants) and your own customized maps :
L.tileLayer.provider('Jawg.Streets', {
variant: '<insert map id here or blank for default variant>',
accessToken: '<insert access token here>'
}).addTo(map);
Thunderforest
In order to use Thunderforest maps, you must register. Once registered, you have an api_key which you have to pass to L.tileLayer.provider in the options:
L.tileLayer.provider('Thunderforest.Landscape', {apikey: '<insert api_key here>'}).addTo(map);
MapTiler Cloud
In order to use MapTiler maps, you must register. Once registered, get your API key from Account->Keys, which you have to pass to L.tileLayer.provider in the options:
L.tileLayer.provider('MapTiler.Streets', {
key: '<insert key here>'
}).addTo(map);
Vemos con el mismo ejemplo anterior un mapa distinto al que mostramos
por defecto, basado en OpenstreetMaps. La función que introducimos es
addProviderTiles().
library(leaflet)
m <- leaflet() %>%
addTiles() %>% # Add default OpenStreetMap map tiles
addMarkers(lng=-0.511828, lat=38.383279, popup="Aula del Máster de Ciencia de Datos") %>%
addProviderTiles(providers$CartoDB.Positron)
m
Uno de los problemas que más pueden fastidiar al crear un mapa de leaflet es que al hacer zoom-out se pueden llegar a ver “varios” planetas Tierra, lo cual no tiene mucho sentido. Esto se puede arreglar definiendo límites al hacer zoom-out y zoom-in. Se pueden cambiar las opciones de la función leaflet. Un ejemplo es el siguiente:
m <- leaflet(options = leafletOptions(minZoom = 11, maxZoom = 16)) %>%
addTiles() %>%
addMarkers(lng=-0.511828, lat=38.383279, popup="Aula del Máster de Ciencia de Datos") %>%
addProviderTiles(providers$CartoDB.DarkMatter)
m
Para dejar el mapa en un zoom fijo y no permitir zoom-out ni
zoom-in, se pueden fijar minZoom y
maxZoom al mismo nivel.
No está restringido a usar un solo mapa base en un mapa; puede apilarlos agregando múltiples capas de mosaicos. En general, esto solo tiene sentido si los mosaicos frontales consisten en mosaicos semitransparentes o tienen una opacidad ajustada a través del argumento de opciones.
m %>% addProviderTiles(providers$MtbMap) %>%
addProviderTiles(providers$CartoDB.PositronNoLabels,
options = providerTileOptions(opacity = 0.15)) %>%
addProviderTiles(providers$Esri.WorldStreetMap)
Utilizamos marcadores (markers) para señalar puntos en
el mapa. Las ubicaciones de los marcadores se expresan en coordenadas de
latitud/longitud y pueden aparecer como iconos o como círculos.
Los datos de puntos para marcadores pueden provenir de una variedad de fuentes:
Objetos SpatialPoints o
SpatialPointsDataFrame (del paquete
sp).
POINT, sfc_POINT y objetos
sf (del paquete sf); solo
se considerarán las dimensiones X e Y.
Matrices numéricas de dos columnas (la primera columna es la longitud, la segunda es la latitud).
Marco de datos con columnas de latitud y logitud. Puede indicar
explícitamente a la función de marcador qué columnas contienen los datos
de coordenadas (por ejemplo,
addMarkers(lng = ~Longitude, lat = ~Latitude)), o dejar que
la función busque columnas
denominadaslat/latitudeylon/lng/long/longitude\
(case insensible).
Simplemente proporcione vectores numéricos como argumentos lng y lat.
Los marcadores de iconos se agregan usando las funciones
addMarkers() o addAwesomeMarkers(). Su
apariencia predeterminada es un pin. Al igual que con la mayoría de las
funciones de las capas, el argumento emergente se puede usar para
agregar un mensaje que se mostrará al hacer clic, y la opción de
etiqueta se puede usar para mostrar una etiqueta de texto al pasar el
mouse o estáticamente.
Los marcadores de círculo addCircleMarkers() son muy
parecidos a los círculos regulares, excepto que su radio en píxeles en
pantalla permanece constante independientemente del nivel de zoom.
Las ventanas emergentes (popups) son pequeños cuadros que contienen HTML arbitrario, que apuntan a un punto específico en el mapa.
Utilice la función addPopups() para agregar una ventana
emergente independiente al mapa.
Un uso común de las ventanas emergentes es que aparezcan cuando se
hace clic en marcadores o formas. Las funciones de marcador y forma en
el paquete Leaflet toman un argumento emergente, donde
puede pasar HTML para adjuntar fácilmente una ventana emergente simple.
Veamos un ejemplo.
library(htmltools)
df <- read.csv(textConnection(
"Name,Lat,Long
Samurai Noodle,47.597131,-122.327298
Kukai Ramen,47.6154,-122.327157
Tsukushinbo,47.59987,-122.326726"
))
leaflet(df) %>% addTiles() %>%
addMarkers(~Long, ~Lat, popup = ~htmlEscape(Name)) %>%
addProviderTiles(providers$CartoDB.DarkMatterOnlyLabels)
Una etiqueta (label) es un contenido textual o HTML que se puede adjuntar a marcadores y formas para que siempre se muestre o se muestre al pasar el ratón. A diferencia de las ventanas emergentes, no es necesario hacer clic en un marcador/polígono para que se muestre la etiqueta.
Simplemente cambiamos la instrucción
addMarkers(~Long, ~Lat, popup = ~htmlEscape(Name)) por
addMarkers(~Long, ~Lat, label = ~htmlEscape(Name)).
Datos en forma de líneas y polígonos pueden venir de una variedad de fuentes:
SpatialPolygons,
SpatialPolygonsDataFrame, Polygons, y
Polygon objetos (de la librería
sp).
SpatialLines, SpatialLinesDataFrame,
Lines, y Line objetos (de la librería
sp).
MULTIPOLYGON, POLYGON,
MULTILINESTRING, y LINESTRING objetos (de la
librería sp)).
map objetos (mediante la función
map()); utilizamos map(fill = TRUE) para
polígonos, FALSE para polylines.
Matrices numéricas de dos culumnas; la primera es la longitud y la segunda la latitud.
Circles
Para dibujar círculos como marcas se usa addCircles().
Los círculos son similares a los marcadores de círculos; la única
diferencia es que los círculos tienen sus radios especificados en
metros, mientras que los marcadores de círculos se especifican en
píxeles. Como resultado, los círculos se escalan con el mapa a medida
que el usuario acerca y aleja el zoom, mientras que los marcadores de
círculos mantienen un tamaño constante en la pantalla independientemente
del nivel de zoom.
Al trazar círculos, solo se requieren los centros (y los radios) de los círculos, por lo que el conjunto de fuentes de datos válidas es diferente al de los polígonos y el mismo que al de los marcadores. Consulte la introducción a Marcadores para obtener detalles específicos.
Vemos un ejemplo:
cities <- read.csv(textConnection("
City,Lat,Long,Pop
Boston,42.3601,-71.0589,645966
Hartford,41.7627,-72.6743,125017
New York City,40.7127,-74.0059,8406000
Philadelphia,39.9500,-75.1667,1553000
Pittsburgh,40.4397,-79.9764,305841
Providence,41.8236,-71.4222,177994
"))
leaflet(cities) %>% addTiles() %>%
addCircles(lng = ~Long, lat = ~Lat, weight = 10, color = "red",
radius = 500, label = ~City) %>%
addProviderTiles(providers$CartoDB)
Podemos hacer que las marcas tengan un tamaño proporcional a la población de la ciudad e introducir una escala de colores también en función de la población.
cities <- read.csv(textConnection("
City,Lat,Long,Pop
Boston,42.3601,-71.0589,645966
Hartford,41.7627,-72.6743,125017
New York City,40.7127,-74.0059,8406000
Philadelphia,39.9500,-75.1667,1553000
Pittsburgh,40.4397,-79.9764,305841
Providence,41.8236,-71.4222,177994
"))
pal <- colorNumeric(
palette = "inferno",
domain = cities$Pop)
leaflet(cities) %>% addTiles() %>%
addCircles(lng = ~Long, lat = ~Lat, weight = 1, color = ~pal(Pop),
radius = ~sqrt(Pop) * 30, label = ~City) %>%
addProviderTiles(providers$CartoDB)
Una parte importante de la visualización espacial es asignar colores a las variables.
tenemos un gran número de funciones relacionadas con la asignación de
color a las variables: colorNumeric, colorBin,
y colorQuantile, colorFactor.
Parámetros comunes
Las funciones de color requieren dos argumentos como mínimo:
palette y domain.
El argumento palette especifica la gama de colores.
Puede tener diversas opciones:
El nombre de una paleta existente en la librería
RColorBrewer, como por ejemplo “RdYlBu”, “Accent”, or
“Greens”. En esta página
podemos ver el conjunto de paletas disponibles en esta
librería.
El nombre de una paleta viridis: “viridis”, “magma”, “inferno”, o “plasma”.
Un vector RGB o los nombres de los colores como por ejemplo
palette( ), c(“#000000”, “#0000FF”, “#FFFFFF”),
topo.colors(10).
Una función que recibe un valor entre 0 y 1 y devuelve un color,
como por ejemplo
colorRamp(c("#000000", "#FFFFFF"), interpolate="spline").
El argumento domain le dice a la función de color el
rango de valores de entrada. Puede pasar NULL aquí para crear una
función de paleta que no tenga un rango preestablecido; el rango se
inferirá de los datos cada vez que invoque la función de paleta. Si usa
una función de paleta varias veces en diferentes datos, es importante
proporcionar un valor no NULL para el dominio para que la escala entre
los datos y los colores sea consistente.
Colores continuos (colorNumeric)
Comenzamos asignado valores GDP directamente a la paleta “Blues” de
ColorBrewer 2. Utilizamos la función
colorNumeric para crear una función de asignación. La
paleta “Blues” solo contiene 9 colores, aunque colorNumeric
interpola estos colores para conseguir una paleta continua.
# Create a continuous palette function
pal <- colorNumeric(
palette = "Blues",
domain = countries$gdp_md_est)
El paquete Leaflet incluye funciones para crear leyendas de colores.
df <- read.csv("https://raw.githubusercontent.com/plotly/datasets/master/2014_world_gdp_with_codes.csv")
colnames(df)[colnames(df) == "GDP..BILLIONS."] <- 'gdp'
colnames(df)[colnames(df) == "COUNTRY"] <- 'country'
head(df)
## country gdp CODE
## 1 Afghanistan 21.71 AFG
## 2 Albania 13.40 ALB
## 3 Algeria 227.80 DZA
## 4 American Samoa 0.75 ASM
## 5 Andorra 4.80 AND
## 6 Angola 131.40 AGO
Ahora vamos a representar los datos del PBI a nivel mundial utilizando leaflet. Tenemos la tabla con las geolocalizaciones de los países.
countries_coor <- read.csv("datos/countries_coor.xls")
colnames(countries_coor)[colnames(countries_coor) == "country"] <- 'country_ID'
colnames(countries_coor)[colnames(countries_coor) == "name"] <- 'country'
head(countries_coor)
## country_ID latitude longitude country
## 1 AD 42.54624 1.601554 Andorra
## 2 AE 23.42408 53.847818 United Arab Emirates
## 3 AF 33.93911 67.709953 Afghanistan
## 4 AG 17.06082 -61.796428 Antigua and Barbuda
## 5 AI 18.22055 -63.068615 Anguilla
## 6 AL 41.15333 20.168331 Albania
Ahora mezclamos las tablas countries_coor y df, que es donde se encuentran los datos del PBI.
tabla <- merge(countries_coor, df, by = "country")
head(tabla)
## country country_ID latitude longitude gdp CODE
## 1 Afghanistan AF 33.93911 67.709953 21.71 AFG
## 2 Albania AL 41.15333 20.168331 13.40 ALB
## 3 Algeria DZ 28.03389 1.659626 227.80 DZA
## 4 American Samoa AS -14.27097 -170.132217 0.75 ASM
## 5 Andorra AD 42.54624 1.601554 4.80 AND
## 6 Angola AO -11.20269 17.873887 131.40 AGO
Ahora ya podemos hacer una representación geográfica. Representamos con círculos el PBI de cada país, siendo el tamaño del círculo una función directa de su valor. También utilizamos una paleta de colores llamada “viridis”.
pal3 <- colorNumeric(
palette = colorRamp(c("blue", "red"), interpolate="spline"),
domain = tabla$gdp)
pal2 <- colorNumeric(
palette = "viridis",
domain = tabla$gdp)
leaflet(tabla) %>% addTiles() %>%
addCircles(lng = ~longitude, lat = ~latitude, weight = 1, color = ~pal3(gdp),
radius = ~gdp * 100, fillOpacity = 0.5, label = paste("País:", tabla$country, "<br>", "PBI $ (billions):", tabla$gdp)) %>%
addProviderTiles(providers$CartoDB.Voyager) %>%
addLegend(pal = pal3, values = ~gdp, opacity = 0.5)
Podemos representar diversas variables en el mismo mapa, simplemente añadiendo las correspondientes capas. Lo vamos a analizar con más detenimiento en los siguientes ejemplos.
Para ello descargamos la librería gapminder, que nos
ofrece una tabla, llamada gapminder, donde aparecen los
datos referentes a los países, el continente, el año (desde el 1952
hasta el 2007, en intervalos de cinco años), la esperanza de vida, la
población y el PBI per cápita (GDP). Nos decargamos dicha tabla para
realizar un tratamiento básico de los datos y llevar a cabo algunas
representaciones.
Lo primero es añadir al conjunto de países sus coordenadas geográficas de longitud y latitud correspondientes. Podemos hacer lo mismo que en caso anterior. Ahora mezclamos las tablas countries_coor y gapminder, que es donde se encuentran los datos del PBI.
library(gapminder)
data(gapminder)
tabla1 <- merge(countries_coor, gapminder, by = "country")
head(tabla1)
## country country_ID latitude longitude continent year lifeExp pop
## 1 Afghanistan AF 33.93911 67.70995 Asia 1962 31.997 10267083
## 2 Afghanistan AF 33.93911 67.70995 Asia 1967 34.020 11537966
## 3 Afghanistan AF 33.93911 67.70995 Asia 1997 41.763 22227415
## 4 Afghanistan AF 33.93911 67.70995 Asia 2007 43.828 31889923
## 5 Afghanistan AF 33.93911 67.70995 Asia 1987 40.822 13867957
## 6 Afghanistan AF 33.93911 67.70995 Asia 2002 42.129 25268405
## gdpPercap
## 1 853.1007
## 2 836.1971
## 3 635.3414
## 4 974.5803
## 5 852.3959
## 6 726.7341
Ahora nos quedamos con los datos mundiales referentes al año 2007, que es el más reciente que aparece en la lista. Para ello, seleccionamos los datos que tienen ese valor en la columna year.
tabla1_2007 <- filter(tabla1, tabla1$year == 2007)
head(tabla1_2007)
## country country_ID latitude longitude continent year lifeExp pop
## 1 Afghanistan AF 33.93911 67.709953 Asia 2007 43.828 31889923
## 2 Albania AL 41.15333 20.168331 Europe 2007 76.423 3600523
## 3 Algeria DZ 28.03389 1.659626 Africa 2007 72.301 33333216
## 4 Angola AO -11.20269 17.873887 Africa 2007 42.731 12420476
## 5 Argentina AR -38.41610 -63.616672 Americas 2007 75.320 40301927
## 6 Australia AU -25.27440 133.775136 Oceania 2007 81.235 20434176
## gdpPercap
## 1 974.5803
## 2 5937.0295
## 3 6223.3675
## 4 4797.2313
## 5 12779.3796
## 6 34435.3674
Ahora vamos a hacer algunas representaciones gráficas. Primero respecto la esperanza de vida.
#Paletas de colores
pal1 <- colorNumeric(
palette = colorRamp(c("blue", "red"), interpolate="spline"),
domain = tabla1_2007$lifeExp)
map <- leaflet(tabla1_2007) %>% addTiles() %>%
addProviderTiles(providers$CartoDB.DarkMatter) %>%
addCircles(lng = ~longitude, lat = ~latitude, weight = 1, color = ~pal1(lifeExp),
radius = ~lifeExp * 2500, fillOpacity = 0.8, popup = paste("País:", tabla1_2007$country, "<br>", "Esperanza vida:", tabla1_2007$lifeExp)) %>%
addLegend(pal = pal1, values = ~lifeExp, opacity = 1)
map
Ahora representamos la población.
#Paletas de colores
pal1 <- colorNumeric(
palette = colorRamp(c("blue", "red"), interpolate="spline"),
domain = tabla1_2007$lifeExp)
pal2 <- colorNumeric(
palette = colorRamp(c("blue", "red"), interpolate="spline"),
domain = tabla1_2007$pop)
pal3 <- colorNumeric(
palette = colorRamp(c("blue", "red"), interpolate="spline"),
domain = tabla1_2007$gdpPercap)
map <- leaflet(tabla1_2007) %>% addTiles() %>%
addProviderTiles(providers$CartoDB.DarkMatter) %>%
addCircles(lng = ~longitude, lat = ~latitude, weight = 1, color = ~pal2(pop),
radius = ~pop /1300, fillOpacity = 0.9, popup = paste("País:", tabla1_2007$country, "<br>", "Población (2007):", tabla1_2007$pop)) %>%
addLegend(pal = pal2, values = ~pop, opacity = 1)
map
Ahora representamos el PBI per cápita.
#Paletas de colores
pal1 <- colorNumeric(
palette = colorRamp(c("blue", "red"), interpolate="spline"),
domain = tabla1_2007$lifeExp)
pal2 <- colorNumeric(
palette = colorRamp(c("blue", "red"), interpolate="spline"),
domain = tabla1_2007$pop)
pal3 <- colorNumeric(
palette = colorRamp(c("blue", "red"), interpolate="spline"),
domain = tabla1_2007$gdpPercap)
map <- leaflet(tabla1_2007) %>% addTiles() %>%
addProviderTiles(providers$CartoDB.DarkMatter) %>%
addCircles(lng = ~longitude, lat = ~latitude, weight = 1, color = ~pal3(gdpPercap),
radius = ~gdpPercap * 5, fillOpacity = 0.8, popup = paste("País:", tabla1_2007$country, "<br>", "PBI per cápita $:", tabla1_2007$gdpPercap)) %>%
addLegend(pal = pal3, values = ~gdpPercap, opacity = 1)
map
Podemos también efectuar una represenatción gráfica conjunta utilizando distintas capas.
#Paletas de colores
pal1 <- colorNumeric(
palette = colorRamp(c("blue", "red"), interpolate="spline"),
domain = tabla1_2007$lifeExp)
pal2 <- colorNumeric(
palette = colorRamp(c("purple", "orange"), interpolate="spline"),
domain = tabla1_2007$pop)
pal3 <- colorNumeric(
palette = colorRamp(c("black", "brown"), interpolate="spline"),
domain = tabla1_2007$gdpPercap)
map <- leaflet(tabla1_2007) %>%
# Base groups
addTiles(group = "Generic") %>%
addProviderTiles(providers$Stamen.TonerBackground, group = "Day") %>%
addProviderTiles(providers$CartoDB.DarkMatter, group = "Night") %>%
# Overlay groups
addCircles(lng = ~longitude, lat = ~latitude, weight = 1, color = ~pal1(lifeExp), radius = ~lifeExp *1800, fillOpacity = 0.5, popup = ~as.character(country), group = "Esperanza Vida") %>%
addCircles(lng = ~longitude, lat = ~latitude, weight = 1, color = ~pal2(pop), radius = ~pop / 1000, fillOpacity = 0.5, popup = ~as.character(country), group = "Población") %>%
addCircles(lng = ~longitude, lat = ~latitude, weight = 1, color = ~pal3(gdpPercap), radius = ~gdpPercap *5, fillOpacity = 0.5, popup = ~as.character(country), group = "PBI per Cápita") %>%
# Layers control
addLayersControl(
baseGroups = c("Generic", "Day", "Night"),
overlayGroups = c("Esperanza Vida", "Población", "PBI per Cápita"),
options = layersControlOptions(collapsed = FALSE)
)
map
A continuación, mostramos uuna visualización relacionada con los tweets que se han producido en la ciudad de Roma durante un período de tiempo. Lo primero que debemos hacer es importar los datos.
tweets_roma <- read.csv("datos/tweets_roma.csv")
head(tweets_roma)
## Created..UTC. Latitude Longitude Text User.Name Language
## 1 2016-05-11 15:02:34 41.81494 12.39986 NA SEVENSunglasses es
## 2 2016-06-18 06:43:36 41.90301 12.50157 NA Preston Dumont en
## 3 2016-06-25 20:13:01 41.90244 12.46600 NA LShafiee en
## 4 2016-06-03 18:33:32 41.88759 12.46958 NA Francesca Giannetto it
## 5 2016-06-16 18:28:31 41.91246 12.46590 NA Donato Robilotta es
## 6 2016-05-25 22:55:54 41.83417 12.47182 NA BrasItalia it
## Retweet.count Country Place Image
## 1 0 España España
## 2 0 Italia Italy http://pbs.twimg.com/media/ClNswv3WYAEWOVC.jpg
## 3 0 Italia Italy http://pbs.twimg.com/media/Cl0pJnuWEAAyVwY.jpg
## 4 0 Italia Italia
## 5 0 Italia Italia
## 6 0 Italia Italia http://pbs.twimg.com/media/CjVlJBWXAAIB1sh.jpg
En esta tabla disponemos de los datos sobre los tweets puestos desde Roma referentes a la fecha y hora, su geolocalización, el ususario que lo ha puesto, el lenguaje, si ha sido retuiteado y el número de veces que lo ha sido. Con todos estos datos, vamos a organizarlos un poco y a seleccionar los que vamos a representar puesto que la tabla contiene más de 200.000 observaciones (tweets).
En primer lugar lo que hacemos es convertir a formato fecha la primera columna.
tweets_roma$Created..UTC. <- as.Date(tweets_roma$Created..UTC.)
Seleccionamos algunas columnas y agrupamos por año.
tweets <- dplyr::select(tweets_roma, Created..UTC.,Latitude,Longitude,User.Name)
colnames(tweets) <- c("Date","latitude","longitude", "username")
tweets$year <- year(tweets$Date)
tweets$month <- month(tweets$Date)
colnames(tweets) <- c("Date","latitude","longitude", "username","year","month")
Filtramos los datos referentes al año 2017
tweets_2017 <- dplyr::filter(tweets, year == 2017)
head(tweets_2017)
## Date latitude longitude username year month
## 1 2017-10-12 41.90310 12.49580 Trendinalia Italia 2017 10
## 2 2017-10-12 41.90000 12.50000 Eridanni Leon 2017 10
## 3 2017-10-12 41.80992 12.44921 AV 2017 10
## 4 2017-10-12 41.90310 12.49580 Trendinalia Italia 2017 10
## 5 2017-10-12 41.90310 12.49580 Trendinalia Italia 2017 10
## 6 2017-10-12 41.81310 12.60072 andrea tupini 2017 10
Ahora ordenamos por meses.
tweets_2017 <- arrange(tweets_2017, month)
head(tweets_2017)
## Date latitude longitude username year month
## 1 2017-02-19 41.90690 12.48795 Elretodetuvida 2017 2
## 2 2017-02-23 41.84951 12.48764 Zarina 2017 2
## 3 2017-03-06 41.88827 12.48122 Kaaru 2017 3
## 4 2017-05-27 41.90689 12.48071 ▒ Donker dag ▒ 2017 5
## 5 2017-05-27 41.89900 12.47978 Andrea Mauri 2017 5
## 6 2017-05-27 41.83830 12.47577 Enrico Pallocca Blog 2017 5
Ahora hacemos un diagrama de barras para tener una idea del número de tweets que se han puesto por mes durante el año 2017.
fig <- plot_ly(tweets_2017, x= ~month, type = "histogram", color = I("orange"),
hovertemplate = paste('<i>Month</i>: %{x}',
'<br><b>Tweets</b>: %{y}<br>'))
fig <- fig %>% layout(title="Number of tweets generated in Roma in 2017",
xaxis=list(dtick = 1, tick0 = 2, tickmode = "linear"),
yaxis=list(title='tweets (miles)'),
bargap=0.1)
fig
Ahora vamos a separar los tweets por meses y para ello construimos unas tablas con los meses 5, 8, 9, 10, 11 y 12, que son donde se han registrado un número mayor de tweets.
tweets_mayo <- filter(tweets_2017, month == 5)
tweets_agosto <- filter(tweets_2017, month == 8)
tweets_septiembre <- filter(tweets_2017, month == 9)
tweets_octubre <- filter(tweets_2017, month == 10)
tweets_noviembre <- filter(tweets_2017, month == 11)
tweets_diciembre <- filter(tweets_2017, month == 12)
Mayo
Hacemos un estudio de los tweets por días.
tweets_mayo$day <- day(tweets_mayo$Date)
tweets_mayo <- arrange(tweets_mayo, day)
Representamos los tweets por día.
fig <- plot_ly(tweets_mayo, x= ~day, type = "histogram", color = I("moccasin"),
hovertemplate = paste('<i>Day</i>: %{x}',
'<br><b>Tweets</b>: %{y}<br>'))
fig <- fig %>% layout(title="Number of tweets generated in Roma in May, 2017",
xaxis=list(dtick = 1, tick0 = 12, tickmode = "linear"),
yaxis=list(title='tweets'),
bargap=0.1)
fig
Vamos a contar el número de tweets en Roma por día, es decir, realizamos manualmente lo que hemos hecho aplicando el gráfico estadístico histograma. Para eso, necesitamos procesar por trozos la tabla que estamos utilizando. Utilizaremos la librería plyr. Dentro de esta librería utilizamos una función que nos es muy útil para trabajar bloques de datos en un data frame. La función es ddply().
ddply() Split Data Frame, Apply Function, And Return Results In A Data Frame.
Un ejemplo sencillo de dicha función es el siguiente:
library(plyr)
df = data.frame(x1=c(0,1,1,1,2,3,3,3),
x2=c(0,1,1,3,2,3,3,2),
x3=c(0,1,1,1,2,3,3,2))
ddply(df, .(x1, x2, x3), nrow)
## x1 x2 x3 V1
## 1 0 0 0 1
## 2 1 1 1 2
## 3 1 3 1 1
## 4 2 2 2 1
## 5 3 2 2 1
## 6 3 3 3 2
Aplicamos esta función para determinar el número de tweets totales por día en Roma en el mes de mayo.
library(plyr)
res <- ddply(tweets_mayo, .(day), summarize, total = length(day))
head(res,10)
## day total
## 1 12 1288
## 2 13 1576
## 3 14 1716
## 4 15 1492
## 5 16 1557
## 6 17 1560
## 7 18 1647
## 8 19 1467
## 9 20 1598
## 10 21 1590
Hacemos lo mismo para los usuarios, es decir, contamos los tweets que ha puesto cada usuario durante el mes de mayo.
res2 <- ddply(tweets_mayo, .(username), summarize, total = length(username))
res2 <- arrange(res2, desc(total))
res2_50 <- filter(res2, total > 50)
res2_50$username <- as.character(res2_50$username)
head(res2, 10)
## username total
## 1 Trendinalia Italia 6871
## 2 Trendsmap Roma 787
## 3 Tendenze Roma 444
## 4 Stigmabase | BR 388
## 5 Valerio Stay Fish 347
## 6 Stigmabase | FR 260
## 7 Rome Weather 175
## 8 Vatican Weather 175
## 9 Sergey Mitrofanov 136
## 10 naike rivelli 111
Representamos estos datos utilizando un típico diagrama de barras. Tomamos sólo los usuarios que han puesto más de 50 tweets.
fig <- res2_50 %>% plot_ly()
fig <- fig %>% add_trace(x = ~username, y = ~total, type = 'bar',
text = ~total, textposition = 'auto',
marker = list(color = 'darkgreen',
line = list(color = 'rgb(8,48,107)', width = 1.5)))
fig <- fig %>% layout(title = "Tweets by username (may, 2017)",
xaxis = list(title = ""),
yaxis = list(title = "Number of tweets"))
fig
Observamos claramente cómo la distribución del número de tweets es muy particular ya que solamente unos pocos usuarios ponen tweetes en las redes en grandes cantidades. Así, por ejemplo, el usuario Trendinalia Italia pone casi 7000 tweets en un mes, mientras que el siguiente usuario es Trendsmap Roma, con casi 800 tweets. Precisamente son empresas que se dedican al análisis de las redes sociales, especialmente los asuntos que son trending topics en cada momento, por lo que su volumen de tweets al día es elevadísimo. Llaman también la atención los usuarios relacionados con la predicción del tiempo. Sin duda, el carácter turístico de la ciudad de Roma marca estas tendencias y esta distribución en los tweets.
Ahora contamos los tweets que ha puesto cada usuario y por día, es decir, contamos los tweets que cada usuario ha puesto y qué días los ha puesto.
res3 <- ddply(tweets_mayo, .(username,day), summarize, total = length(username))
res3 <- arrange(res3, desc(total))
head(res3,10)
## username day total
## 1 Trendinalia Italia 22 454
## 2 Trendinalia Italia 23 447
## 3 Trendinalia Italia 24 442
## 4 Trendinalia Italia 26 439
## 5 Trendinalia Italia 27 434
## 6 Trendinalia Italia 14 433
## 7 Trendinalia Italia 18 432
## 8 Trendinalia Italia 25 431
## 9 Trendinalia Italia 20 422
## 10 Trendinalia Italia 16 411
Vamos a intentar contabilizar cuántos tweets se han puesto desde cada posición geográfica. queremos obtener una tabla donde aparezca la posición geográfica desde la que se han puesto tweets en el mes de mayo, cuántos se han puesto desde cada lugar y el usuario que los ha puesto.
res4 <- ddply(tweets_mayo, .(longitude,latitude, username), summarize, total = length(latitude))
res4 <- arrange(res4, desc(total))
head(res4,10)
## longitude latitude username total
## 1 12.49580 41.90310 Trendinalia Italia 6871
## 2 12.48230 41.89550 Trendsmap Roma 787
## 3 12.49580 41.90310 Tendenze Roma 444
## 4 12.49529 41.94105 Stigmabase | BR 367
## 5 12.49529 41.94105 Stigmabase | FR 250
## 6 12.50000 41.90000 Rome Weather 175
## 7 12.45000 41.90000 Vatican Weather 175
## 8 12.50000 41.90000 naike rivelli 106
## 9 12.51123 41.99706 Stigmabase | UN 90
## 10 12.49637 41.90278 TMJ-ITA Jobs 73
Ahora, en la tabla res4 hemos conseguido reunir tres columnas: la primera me indica la longitud y la segunda la latitud; la tercera me indica el número de tweets que se realizan esde esa misma posición. Ahora la idea es establecer un gráfico con los tweets donde el tamaño de cada punto esté en función del numero de tweets. Lo hacemos con leaflet.
#Paletas: Greens, Blues, Accent, Spectral, inferno, plasma, magma, viridis, heat, RdYlBu
df <- res4
pal3 <- colorNumeric(
palette = "PRGn",
domain = df$total)
leaflet(df) %>% addTiles() %>%
addCircles(lng = ~longitude, lat = ~latitude, weight = 1, color = ~pal3(total),
radius = ~sqrt(total*10), fillOpacity = 0.5, popup = paste("Usuario:", df$username, "<br>", "Tweets (mayo 2017):", df$total)) %>%
addProviderTiles(providers$CartoDB.Voyager) %>%
addLegend(pal = pal3, values = ~total, opacity = 1)
Hemos analizado los datos correspondientes al mes de mayo referentes al número de tweets emitidos por cada usuario, la fecha en las que lo emite y la geolocalización del mismo. No hemos analizado si los datos que disponemos corresponden con todos los días del mes o, si por el contario, solo disponemos de algunos días concretos de los que se disponen datos. Por tanto, nos hacemos la primera pregunta:
Los tweets analizados recogidos en 2017 se corresponden con algunos meses concretos. ¿Cómo es la distribución de tweets a lo largo de esos meses? ¿Disponemos de datos todos los días del mes estudiado o solo de algunos días? ¿Son representativos esos días para extraer conclusiones generales?
Para contestar a esta pregunta resulta interesante definir una nueva tabla donde podamos determinar los tweets emitidos por mes y por día dentro del mes. Para hacer esto nos faltarís definir una nueva columna donde aparezca el día de la fecha concreta.
tweets_2017$day <- day(tweets_2017$Date)
Ahora vamos a construir una nueva tabla donde aparezcan los tweets ordenados por mes y día, para poder estimar la distribución de tweets a lo largo del tiempo.
tweets_2017_org <- ddply(tweets_2017, .(month,day), summarize, total = length(day))
head(tweets_2017_org)
## month day total
## 1 2 19 1
## 2 2 23 1
## 3 3 6 1
## 4 5 12 1288
## 5 5 13 1576
## 6 5 14 1716
Ahora representamos gráficamente.
fig <- tweets_2017_org %>%
plot_ly(
x = ~day,
y = ~total,
frame = ~month,
text = ~total,
hoverinfo = "text",
type = 'scatter',
mode = 'markers'
)
fig <- fig %>% layout(
title = "Número de tweets por día y mes en 20017 en Roma",
xaxis = list(
title = "Dia"
),
yaxis = list(
title = "Número de tweets"
)
)
fig <- fig %>%
animation_opts(1000, easing = "elastic", redraw = FALSE) %>%
animation_button(y = 1000, xanchor = "right", y = 0, yanchor = "bottom") %>%
animation_slider(currentvalue = list(prefix = "mes: ", font = list(color="orange")))
fig
Del gráfico animado anerior podemos observar que de la mayoría de los meses disponemos de datos dispersos, unos cuantos días seguidos, aunque no todo el mes completo. Sin embargo, se observa que tenemos dos meses, octubre y noviembre, donde disponemos de datos prácticamente casi todos los días y existen pocas fluctuaciones en el número de tweets de unos días y otros, presentando unos valores que en principio pensamos que podemos analizar como representativos.
Ahora nos hacemos una cuestión que vamos a tratar de responder con los datos.
¿Podemos observar un comportamiento y un patrón similar en los tweets contabilizados de los meses de octubre y noviembre que los patrones y características de los recogidos en el mes de mayo? ¿Existe una distribución similar de los tweets durante los días de esos meses? ¿Son los mismos usuarios los que más tweets ponen durante octubre y noviembre?
Para reponder estas cuestiones analizamos los datos que nos ofrece la tabla tweets_2017_org.
#Hacemos el mes de octubre
#Construimos los tweets de agosto por dias
tweets_octubre$day <- day(tweets_octubre$Date)
tweets_octubre <- arrange(tweets_octubre, day)
# Construimos la tabla con los tweets por día
res_oc <- ddply(tweets_octubre, .(day), summarize, total = length(day))
colnames(res_oc) <- c("day","total_oc")
# Construimos tablas con los usuarios de tweets
res2_oc <- ddply(tweets_octubre, .(username), summarize, total = length(username))
res2_oc <- arrange(res2_oc, desc(total))
colnames(res2_oc) <- c("username","total_oc")
res2oc_50 <- filter(res2_oc, total_oc > 50)
res2oc_50$username <- as.character(res2oc_50$username)
# Tabla con los tweets de los usuarios por día
res3_oc <- ddply(tweets_octubre, .(username,day), summarize, total = length(username))
res3_oc <- arrange(res3_oc, desc(total))
# Tabla de tweets de usuarios durante todo el mes por geolocalización.
res4_oc <- ddply(tweets_octubre, .(longitude,latitude, username), summarize, total = length(latitude))
res4_oc <- arrange(res4_oc, desc(total))
colnames(res4_oc) <- c("longitude", "latitude", "username","total_oc")
#Hacemos el mes de noviembre
#Construimos los tweets de agosto por dias
tweets_noviembre$day <- day(tweets_noviembre$Date)
tweets_noviembre <- arrange(tweets_noviembre, day)
# Construimos la tabla con los tweets por día
res_no <- ddply(tweets_noviembre, .(day), summarize, total = length(day))
colnames(res_no) <- c("day","total_no")
# Construimos tablas con los usuarios de tweets
res2_no <- ddply(tweets_noviembre, .(username), summarize, total = length(username))
res2_no <- arrange(res2_no, desc(total))
colnames(res2_no) <- c("username","total_no")
res2no_50 <- filter(res2_no, total_no > 50)
res2no_50$username <- as.character(res2no_50$username)
# Tabla con los tweets de los usuarios por día
res3_no <- ddply(tweets_noviembre, .(username,day), summarize, total = length(username))
res3_no <- arrange(res3_no, desc(total))
# Tabla de tweets de usuarios durante todo el mes por geolocalización.
res4_no <- ddply(tweets_noviembre, .(longitude,latitude, username), summarize, total = length(latitude))
res4_no <- arrange(res4_no, desc(total))
colnames(res4_no) <- c("longitude", "latitude", "username","total_no")
Hemos construido tablas similares a las construidas para el mes de mayo, pero ahora para el mes de octubre y noviembre. Ahora se trata de visualizar y comparar estos resultados.
En primer lugar vamos a hacer una comparativa del número total de tweets que se han emitido por día los meses de octubre y noviembre. Para ello, construimos una nueva tabla mezclando los datos de las tablas referentes a los meses de octubre y noviembre, que son res_oc y res_no.
res_oc_no <- merge(res_oc, res_no, by = "day")
head(res_oc_no)
## day total_oc total_no
## 1 1 1398 867
## 2 2 1288 1449
## 3 3 1355 1311
## 4 4 1481 1351
## 5 5 1487 1310
## 6 6 1459 1321
Hacemos una representación gráfica.
a <- list(
title = "Día",
autotick = FALSE,
ticks = "outside",
tick0 = 0,
ticklen = 5,
tickwidth = 2,
tickcolor = toRGB("green")
)
fig <- plot_ly(res_oc_no, x = ~day, y = ~total_oc, name = 'Octubre', type = 'scatter', mode = 'lines+markers')
fig <- fig %>% add_trace(y = ~total_no, name = 'Noviembre', mode = 'lines+markers') %>%
layout(
title = "Tweets en Octubre y Noviembre por días en Roma (2017)",
xaxis = a,
yaxis = list(title = "Número de tweets")
)
fig
Ahora vamos a representar el número de tweets por usuario durante los meses de octubre y noviembre. También vamos a añadir los datos que tenemos de mayo, con los que ya hemos trabajado. Debemos construir una tabla con los datos mezclados de diversas tablas, como son res2, res2_oc, res2_no. Tenemos 6233 usuarios que pusieron algún tweet en mayo, 6077 usuarios en octubre y 6029 en noviembre. Notemos que el número de usuarios es parecido en los tres meses, aunque del mes de mayo disponemos de menos datos. La tabla que construimos refleja los usuarios que han puesto algún tweet en los tres meses analizados.
#Mezclamos los meses de octubre y noviembre
res2_oc_no <- merge(res2_oc, res2_no, by = "username")
#Mezclamos con el mes de mayo
res2_oc_no <- merge(res2, res2_oc_no, by = "username")
res2_oc_no <- arrange(res2_oc_no, desc(total))
head(res2_oc_no)
## username total total_oc total_no
## 1 Trendinalia Italia 6871 11086 9310
## 2 Trendsmap Roma 787 569 718
## 3 Tendenze Roma 444 500 495
## 4 Stigmabase | BR 388 1056 1144
## 5 Valerio Stay Fish 347 202 184
## 6 Stigmabase | FR 260 1423 1552
Según la tabla que hemos construido, tenemos 1757 usuarios que han puesto al menos un tweet durante los meses de octubre y noviembre. El número de usuarios que han puesto tweets en los tres meses es 811. Vamos a representar los 25 primeros usuarios y los tweets durante esos meses.
res2_oc_no_25 <- res2_oc_no[1:25, ]
fig <- plot_ly(res2_oc_no_25, x = ~username, y = ~total, name = 'Mayo', type = 'scatter', mode = 'markers') %>%
add_trace(y = ~total_oc, name = 'Octubre', mode = 'markers') %>%
add_trace(y = ~total_no, name = 'Noviembre', mode = 'markers') %>%
layout(
title = "Usuarios de los tweets en Roma (2017)",
yaxis = list(title = "Número de tweets")
)
fig
Observamos claramente el mismo patrón en los meses analizados. Existe un usuario (Trendinalia Roma) que pone miles de tweets en un mes y supera con mucho al resto.
¿Cuántos tweets se han puesto por día durante los meses de octubre y noviembre y qué usuario los ha puesto? ¿Podemos representar gráficamente estos datos?
Vamos a representar estos datos. Para ello, necesitamos trabajar con las tablas res3_oc y res3_no.
#Cambiamos de nombre las columnas correspondientes
colnames(res3_oc) <- c("username_oc","day", "total_oc")
res3_oc$username_oc <- as.character(res3_oc$username_oc)
colnames(res3_no) <- c("username_no","day", "total_no")
res3_no$username_no <- as.character(res3_no$username_no)
#Mezclamos las tablas.
res3_oc_no <- merge(res3_oc, res3_no, by = "day")
head(res3_oc_no)
## day username_oc total_oc username_no total_no
## 1 1 Marika 🌺 2 novia de la galleta 1
## 2 1 Marika 🌺 2 Matthijs 1
## 3 1 Marika 🌺 2 Vincenzo Tirittera 1
## 4 1 Marika 🌺 2 Francesco 1
## 5 1 Marika 🌺 2 Massy 1
## 6 1 Marika 🌺 2 Andrea Fatica 2
La tabla que obtenemos mezclando estos datos tiene más de 7 millones de registros. Contabilizamos todos los tweets que se han contabilizado, por días durante estos dos meses, y por usuario que lo ha emitido. Con el fin de simplificar un poco la visualización, ya que representar más de 7 millones de datos no tiene mucho sentido en este caso, podemos establecer un número mínimo de tweets por día de cada usuario. De esta forma, representamos los usuarios más activos y los días de emisión del tweet.
res3_oc_no <- filter(res3_oc_no, total_oc > 10 & total_no > 10)
En concreto, representamos los usuarios que han emitido más de 10 tweets en un día.
fig <- plot_ly(res3_oc_no, x = ~day, y = ~total_oc, name = 'Octubre', type = 'scatter', mode = 'markers',
marker = list(size = ~total_oc, sizeref = 4, sizemode = 'area'),
text = ~username_oc,
hovertemplate = paste(
"<b>%{text}</b><br><br>",
"<i>Tweets:</i>: %{y}<br>",
"<i>Día:</i>: %{x}"
)) %>%
add_trace(y = ~total_no, name = 'Noviembre', mode = 'markers',
marker = list(size = ~total_no, sizeref = 4, sizemode = 'area'),
color = "red",
text = ~username_no,
hovertemplate = paste(
"<b>%{text}</b><br><br>",
"<i>Tweets:</i>: %{y}<br>",
"<i>Día:</i>: %{x}"
)) %>%
layout(
title = "Tweets en Roma (oct y nov de 2017)",
xaxis = list(title = "Día"),
yaxis = list(title = "Número de tweets")
)
fig
Ahora vamos a realizar una representación geográfica de los tweets durante estos meses de octubre y noviembre. Sin embargo, ahora la represenatción va a ser sesgada, ya que vamos a geolocalizar los usuarios que han puesto más de 10 tweets durante el mes correspondiente. Buscamos la localización geográfica de los usuarios más activos en tweeter en esta ciudad.
#Paletas: Greens, Blues, Accent, Spectral, inferno, plasma, magma, viridis, heat, RdYlBu
df <- filter(res4_oc, res4_oc$total_oc >10)
pal3 <- colorNumeric(
palette = "PRGn",
domain = df$total_oc)
leaflet(df) %>% addTiles() %>%
addCircles(lng = ~longitude, lat = ~latitude, weight = 1, color = ~pal3(total_oc),
radius = ~sqrt(total_oc*100), fillOpacity = 0.5, popup = paste("Usuario:", df$username, "<br>", "Tweets (oct 2017):", df$total_oc)) %>%
addProviderTiles(providers$CartoDB) %>%
addLegend(pal = pal3, values = ~total_oc, opacity = 1)
#Paletas: Greens, Blues, Accent, Spectral, inferno, plasma, magma, viridis, heat, RdYlBu
df <- filter(res4_no, res4_no$total_no >10)
pal3 <- colorNumeric(
palette = "PRGn",
domain = df$total_no)
leaflet(df) %>% addTiles() %>%
addCircles(lng = ~longitude, lat = ~latitude, weight = 1, color = ~pal3(total_no),
radius = ~sqrt(total_no*100), fillOpacity = 0.5, popup = paste("Usuario:", df$username, "<br>", "Tweets (nov 2017):", df$total_no)) %>%
addProviderTiles(providers$CartoDB) %>%
addLegend(pal = pal3, values = ~total_no, opacity = 1)
Observando simplemente las dos imágenes, apreciamos los patrones comunes en cuanto a la distribución de tweets en los meses estudiados.
Finalmente, vamos a escribir algunas de las tablas que hemos construido en este capítulo con el fin de utilizarlas, si fuera necesario, en otros análisis de datos en capítulos posteriores. Por ejemplo, guardamos las tablas de octubre y noviembre que hemos ido generando:
write.csv(res2_oc, file = "/Volumes/Work/Matematicas/UNIVERSIDAD/Master Data Science/Apuntes/6_flexdashboard/tablas/res2_oc.csv")
write.csv(res2_no, file = "/Volumes/Work/Matematicas/UNIVERSIDAD/Master Data Science/Apuntes/6_flexdashboard/tablas/res2_no.csv")
write.csv(res_oc, file = "/Volumes/Work/Matematicas/UNIVERSIDAD/Master Data Science/Apuntes/6_flexdashboard/tablas/res_oc.csv")
write.csv(res_no, file = "/Volumes/Work/Matematicas/UNIVERSIDAD/Master Data Science/Apuntes/6_flexdashboard/tablas/res_no.csv")
write.csv(res3_oc, file = "/Volumes/Work/Matematicas/UNIVERSIDAD/Master Data Science/Apuntes/6_flexdashboard/tablas/res3_oc.csv")
write.csv(res3_no, file = "/Volumes/Work/Matematicas/UNIVERSIDAD/Master Data Science/Apuntes/6_flexdashboard/tablas/res3_no.csv")
write.csv(res4_oc, file = "/Volumes/Work/Matematicas/UNIVERSIDAD/Master Data Science/Apuntes/6_flexdashboard/tablas/res4_oc.csv")
write.csv(res4_no, file = "/Volumes/Work/Matematicas/UNIVERSIDAD/Master Data Science/Apuntes/6_flexdashboard/tablas/res4_no.csv")
write.csv(res_oc_no, file = "/Volumes/Work/Matematicas/UNIVERSIDAD/Master Data Science/Apuntes/6_flexdashboard/tablas/res_oc_no.csv")
write.csv(res2_oc_no, file = "/Volumes/Work/Matematicas/UNIVERSIDAD/Master Data Science/Apuntes/6_flexdashboard/tablas/res2_oc_no.csv")
write.csv(res3_oc_no, file = "/Volumes/Work/Matematicas/UNIVERSIDAD/Master Data Science/Apuntes/6_flexdashboard/tablas/res3_oc_no.csv")
write.csv(res2oc_50, file = "/Volumes/Work/Matematicas/UNIVERSIDAD/Master Data Science/Apuntes/6_flexdashboard/tablas/res2oc_50.csv")
write.csv(res2no_50, file = "/Volumes/Work/Matematicas/UNIVERSIDAD/Master Data Science/Apuntes/6_flexdashboard/tablas/res2no_50.csv")